import { ref, reactive, watch,nextTick,getCurrentInstance,onBeforeUnmount } from 'vue'
import type { ComputedRef } from 'vue'
import type {
	SwipeActionItemProps
} from "../../libs/config/propsType";
import type {
	SwipeActionContext,
	SwipeActionItemContext
} from '../../libs/tokens'
import {
		getPx,
		getDuration
	} from '../../libs/utils/_utils'
import {
		getNvueRect
	} from '../../libs/utils'


export const useHooks = (props : ComputedRef<SwipeActionItemProps>, parent ?: SwipeActionContext) => {
	
	// #ifdef APP-NVUE
	// nvue操作dom的库，用于获取dom的尺寸信息
	const dom = uni.requireNativePlugin('dom');
	const bindingX = uni.requireNativePlugin('bindingx');
	const animation = uni.requireNativePlugin('animation');
	// #endif
	
	const ctx = getCurrentInstance()
	const status = ref('close')
	
	const size = ref({
		buttons: [{
			width: 0,
			height: 0,
			top: 0,
			left: 0,
			right: 0
		}] as UniApp.NodeInfo[],
		show: props.value.show,
		disabled: props.value.disabled,
		threshold: props.value.threshold,
		duration: props.value.duration
	})
	const swipeActionItemContentRef = ref()
	// 所有按钮的总宽度
	const buttonsWidth = ref(0)
	// 是否正在移动中
	const moving = ref(false)
	
	// 关闭单元格，用于打开一个，自动关闭其他单元格的场景
	const closeHandler = () => {
		// #ifdef APP-NVUE
		if (status.value === 'open') {
			// 如果在打开状态下，进行点击的话，直接关闭单元格
			moveCellByAnimation('close')
			unbindBindingX()
		}
		return 
		// #endif
		status.value = 'close'
	}
	
	const closeOther = () => {
		parent && parent.closeOther(context)
	}
	
	
	const context: SwipeActionItemContext = reactive({
		props,
		closeHandler
	})
	
	const setState = (value:string) => {
		status.value = value
	}
	// #ifdef APP-NVUE
	
	// 点击单元格
	const clickHandler = () => {
		// 如果在移动中被点击，进行忽略
		if (moving.value) return
		// 尝试关闭其他打开的单元格
		closeOther()
		if (status.value === 'open') {
			// 如果在打开状态下，进行点击的话，直接关闭单元格
			moveCellByAnimation('close')
			unbindBindingX()
			return 
		}
	}
	
	let panEvent:any
	
	// 滑动单元格
	const onTouchstart = (e:any) => {
		// 如果当前正在移动中，或者disabled状态，则返回
		if (moving.value || props.value.disabled) {
			return unbindBindingX()
		}
		if (status.value === 'open') {
			// 如果在打开状态下，进行点击的话，直接关闭单元格
			moveCellByAnimation('close')
			unbindBindingX()
			return 
		}
		// 特殊情况下，e可能不为一个对象
		e?.stopPropagation && e.stopPropagation()
		e?.preventDefault && e.preventDefault()
		moving.value = true
		// 获取元素ref
		
		let expression = `min(max(${-buttonsWidth.value}, x), 0)`
		// 尝试关闭其他打开的单元格
		closeOther()
	
		// 阿里为了KPI而开源的BindingX
		panEvent = bindingX.bind({
			anchor: swipeActionItemContentRef.value,
			eventType: 'pan',
			props: [{
				element: swipeActionItemContentRef.value,
				// 绑定width属性，设置其宽度值
				property: 'transform.translateX',
				expression
			}]
		}, (res:any) => {
			moving.value = false
			if (res.state === 'end' || res.state === 'exit') {
				const deltaX = res.deltaX
				if (deltaX <= -buttonsWidth.value || deltaX >= 0) {
					// 如果触摸滑动的过程中，大于单元格的总宽度，或者大于0，意味着已经动过滑动达到了打开或者关闭的状态
					// 这里直接进行状态的标记
					nextTick(() => {
						status.value = deltaX <= -buttonsWidth.value ? 'open' : 'close'
					})
				} else if (Math.abs(deltaX) > getPx(props.value.threshold||"")) {
					// 在移动大于阈值、并且小于总按钮宽度时，进行自动打开或者关闭
					// 移动距离大于0时，意味着需要关闭状态
					if (Math.abs(deltaX) < buttonsWidth.value) {
						moveCellByAnimation(deltaX > 0 ? 'close' : 'open')
					}
				} else {
					// 在小于阈值时，进行关闭操作(如果在打开状态下，将不会执行bindingX)
					moveCellByAnimation('close')
				}
			}
		})
	}
	
	// 释放bindingX
	const unbindBindingX = () => {
		// 释放上一次的资源
		if (panEvent?.token != 0) {
			bindingX.unbind({
				token: panEvent?.token,
				// pan为手势事件
				eventType: 'pan'
			})
		}
	}
	// 查询按钮节点信息
	const queryRect = () => {
		// 历遍所有按钮数组，通过getRectByDom返回一个promise
		const promiseAll = props.value.options?.map((item, index) => {
			return getNvueRect((ctx?.refs as any)[`e-swipe-action-item__right__button-${index}`][0])
		})||[]
		// 通过promise.all方法，让所有按钮的查询结果返回一个数组的形式
		Promise.all(promiseAll).then(sizes => {
			// this.buttons = sizes
			// 计算所有按钮总宽度
			buttonsWidth.value = sizes.reduce((sum, cur) => sum + cur.width!, 0)
		})
	}

	// 移动单元格到左边或者右边尽头
	const moveCellByAnimation = (_status = 'open') => {
		if (moving.value) return
		// 标识当前状态
		moving.value = true
		const x = _status === 'open' ? -buttonsWidth.value : 0
		animation.transition(swipeActionItemContentRef.value, {
			styles: {
				transform: `translateX(${x}px)`,
			},
			duration: getDuration(props.value.duration, false),
			timingFunction: 'ease-in-out'
		}, () => {
			moving.value = false
			status.value = _status
			unbindBindingX()
		})
	}
	
	
	watch(() => props.value.show, (n) => {
		if (n) {
			moveCellByAnimation('open')
		} else {
			moveCellByAnimation('close')
		}
	})
	
	const nvueInit = () => {
		queryRect()
	}
	
	onBeforeUnmount(() => {
		unbindBindingX()
	})
	// #endif
	
	return {
		ctx,
		status,
		size,
		swipeActionItemContentRef,
		context,
		closeHandler,
		closeOther,
		setState,
		// #ifdef APP-NVUE
		clickHandler,
		onTouchstart,
		nvueInit
		// #endif
	}
}
